#pragma once

#include <common_header.h>
#include <mutex>

namespace utl
{
	template<typename T>
	class StackIterator;

	template<typename T, typename Allocator, typename Storage>
	class stack
	{
	public:
		using this_type = stack<T, Allocator, Storage>;
		using iterator = StackIterator<this_type*>;
		using size_type = iterator::size_type;
		using value_type = T;
		using pointer = T*;
		using reference = T&;
	public:
		stack();
		iterator begin();
		iterator end();
		
		reference at(size_type index);

		//void push();


	private:
		Allocator allocation;
		Storage m_begin;
		size_type size;
		size_type capacity;
		std::mutex mem_locker;
	};

	template<typename T>
	class StackIterator
	{
	public:
		using size_type = u64;
	public:
		StackIterator(T, size_type);
	private:
		T container;
		size_type index;
	};

	template<typename T>
	inline StackIterator<T>::StackIterator(T c, size_type i) : container{ c }, index{ i }
	{}

	template<typename T, typename Allocator, typename Storage>
	inline stack<T, Allocator, Storage>::stack(): 
		allocation{ "UTL STACK" },
		m_begin{ nullptr },
		size{},
		capacity{},
		mem_locker{}
	{}

	template<typename T, typename Allocator, typename Storage>
	inline stack<T, Allocator, Storage>::iterator stack<T, Allocator, Storage>::begin()
	{
		return iterator{ this,0ull };
	}

	template<typename T, typename Allocator, typename Storage>
	inline stack<T, Allocator, Storage>::iterator stack<T, Allocator, Storage>::end()
	{
		return iterator{ this,capacity };
	}

	template<typename T, typename Allocator, typename Storage>
	inline stack<T, Allocator, Storage>::reference stack<T, Allocator, Storage>::at(size_type index)
	{
		return m_begin[index];
	}

	
}